﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StatConnectorCommonLib;
using STATCONNECTORSRVLib;

namespace Common
{
    /// <summary>
    /// 概率密度为正态分布的函数辅助方法,包括概率和分位点的计算
    /// </summary>
    public class NormDistHelper
    {
        private static StatConnector sc1;
        static NormDistHelper()
        {
            sc1 = new STATCONNECTORSRVLib.StatConnectorClass();
            sc1.Init("R");
        }

        #region 一元正态分布函数

        /// <summary>
        /// 标准正态下的概率
        /// </summary>
        /// <param name="quantile">分位数</param>
        /// <returns></returns>
        public static double PNorm(double quantile)
        {
            return PNorm(quantile, 0, 1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="quantile">分位数</param>
        /// <param name="mean">期望</param>
        /// <param name="sd">标准差</param>
        /// <returns></returns>
        public static double PNorm(double quantile, double mean, double sd)
        {
            //sc1.Init("R");
            sc1.SetSymbol("x", quantile);
            sc1.SetSymbol("e1", mean);
            sc1.SetSymbol("sd1", sd);
            sc1.Evaluate("y<-pnorm(x,e1,sd1)");
            object pnorm = sc1.GetSymbol("y");
            return (double)pnorm;
        }


        public static double QNorm(double probability)
        {
            return QNorm(probability, 0, 1);
        }

        public static double QNorm(double probability, double mean, double sd)
        {
            //sc1.Init("R");
            sc1.SetSymbol("x", probability);
            sc1.SetSymbol("e1", mean);
            sc1.SetSymbol("sd1", sd);
            sc1.Evaluate("y<-qnorm(x,e1,sd1)");
            object pnorm = sc1.GetSymbol("y");
            return (double)pnorm;
        }

        /// <summary>
        /// 求概率密度值
        /// </summary>
        /// <param name="probability"></param>
        /// <returns></returns>
        public static double DNorm(double probability)
        {
            return DNorm(probability, 0, 1);
        }

        public static double DNorm(double probability, double mean, double sd)
        {
            //sc1.Init("R");
            sc1.SetSymbol("x", probability);
            sc1.SetSymbol("e1", mean);
            sc1.SetSymbol("sd1", sd);
            sc1.Evaluate("y<-dnorm(x,e1,sd1)");
            object pnorm = sc1.GetSymbol("y");
            return (double)pnorm;
        }

        #endregion

        #region 二元正态分布函数
        //public static double PBvNorm(double quantile)
        //{
        //    return PBvNorm(quantile, 0, 1);
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="corrs"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public static double PBvNorm(double lower1, double upper1, double lower2, double upper2, double mean1, double mean2, double[,] sigmas)
        {
            string evaStringFmt = "y<-pmvnorm(c({0},{1}),c({2},{3}),c({4},{5}),sigma=sigmas1)";


            //需要传入协方差矩阵
            sc1.EvaluateNoReturn("library(mvtnorm)");

            sc1.SetSymbol("sigmas1", sigmas);
            string evaStr = string.Format(evaStringFmt, Fmt(lower1), Fmt(lower2), Fmt(upper1), Fmt(upper2), mean1, mean2);
            sc1.Evaluate(evaStr);
            object pnorm = sc1.GetSymbol("y");


            return (double)pnorm;
        }

        private static string Fmt(double input)
        {
            if (input == double.PositiveInfinity)
                return "Inf";
            if (input == double.NegativeInfinity)
                return "-Inf";
            else
                return input.ToString();
        }
        #endregion
    }
}
